package cs342.uwosh.edu.ContactsApp;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ContactsDataSource {

	private final static String[] ALL_COLUMNS = {
		ContactsDatabaseHelper.COL_ID,
		ContactsDatabaseHelper.COL_NAME,
		ContactsDatabaseHelper.COL_ADDRESS,
		ContactsDatabaseHelper.COL_HOME_PHONE_NUMBER,
		ContactsDatabaseHelper.COL_CELL_PHONE_NUMBER,
		ContactsDatabaseHelper.COL_ALTERNATE_PHONE_NUMBER,
		ContactsDatabaseHelper.COL_EMAIL,
		ContactsDatabaseHelper.COL_COMMENT
	};
	
	// Database fields
	private SQLiteDatabase database;
	private ContactsDatabaseHelper dbHelper;
	

	public ContactsDataSource(Context context) {
		dbHelper = new ContactsDatabaseHelper(context);
	}

	public void open() throws SQLException {
		database = dbHelper.getWritableDatabase();
	}

	public void close() {
		dbHelper.close();
	}
	public Contact createContact(String name, String address, String cell, String homePhone, 
			String altPhone, String email, String comment) {
		return createContact(new Contact(0, name, address, cell, homePhone, 
								altPhone,  email,  comment));
	}
	@SuppressWarnings("unchecked")
	public Contact createContact(Contact contact) {
		
        
		ContentValues values = new ContentValues();
		values.put(ContactsDatabaseHelper.COL_NAME, contact.getName());
		values.put(ContactsDatabaseHelper.COL_ADDRESS, contact.getAddress());
		values.put(ContactsDatabaseHelper.COL_HOME_PHONE_NUMBER, contact.getHomePhoneNumber());
		values.put(ContactsDatabaseHelper.COL_CELL_PHONE_NUMBER, contact.getCellPhoneNumber());
		values.put(ContactsDatabaseHelper.COL_ALTERNATE_PHONE_NUMBER, contact.getAlternatePhoneNumber());
		values.put(ContactsDatabaseHelper.COL_EMAIL, contact.getEmail());
		values.put(ContactsDatabaseHelper.COL_COMMENT, contact.getComments());
		
		Contact contact2 = (Contact)DatabaseThread.call(new DatabaseThread(database, values) {
	        public Object call() {
				long insertId = database.insert(ContactsDatabaseHelper.TABLE_CONTACTS, null,
						(ContentValues)args[0]);
				// To show how to query
				Cursor cursor = database.query(ContactsDatabaseHelper.TABLE_CONTACTS,
						ALL_COLUMNS, ContactsDatabaseHelper.COL_ID + " = " + insertId, null,
						null, null, null);
				cursor.moveToFirst();
				return cursorToContact(cursor);
	        }
        });
		
        if(contact2 != null) contact = contact2;
        return contact;
	}

	@SuppressWarnings("rawtypes")
	public void deleteContact(Contact contact) {
		long id = contact.getID();
		
		DatabaseThread.run(new DatabaseThread(database, id) {
			public void run() {
				database.delete(ContactsDatabaseHelper.TABLE_CONTACTS, ContactsDatabaseHelper.COL_ID
						+ " = " + args[0], null);
			}
		});
		
	}
	
	
	@SuppressWarnings("rawtypes")
	public Contact editContact(Contact contact) {
		//extract attributes of contacts and insert into values' hashmap
		ContentValues values = new ContentValues();
		values.put(ContactsDatabaseHelper.COL_NAME, contact.getName());
		values.put(ContactsDatabaseHelper.COL_ADDRESS, contact.getAddress());
		values.put(ContactsDatabaseHelper.COL_HOME_PHONE_NUMBER, contact.getHomePhoneNumber());
		values.put(ContactsDatabaseHelper.COL_CELL_PHONE_NUMBER, contact.getCellPhoneNumber());
		values.put(ContactsDatabaseHelper.COL_ALTERNATE_PHONE_NUMBER, contact.getAlternatePhoneNumber());
		values.put(ContactsDatabaseHelper.COL_EMAIL, contact.getEmail());
		values.put(ContactsDatabaseHelper.COL_COMMENT, contact.getComments());
		
		// Update Db
		DatabaseThread.run(new DatabaseThread(database, values, contact) {
			public void run() {
				database.update(ContactsDatabaseHelper.TABLE_CONTACTS,
						(ContentValues) args[0], ContactsDatabaseHelper.COL_ID
								+ " = " + ((Contact) args[1]).getID(), null);
			}
		});
		return contact;
	}
	
	public Contact getContact(long ID) {
		Contact contact;
		if(ID == -1) {
			//Default Contact
			contact = new Contact();
		} else {
			//Query Database
			@SuppressWarnings("unchecked")
			Cursor cursor = DatabaseThread.call(new DatabaseThread(database, ID) {
				public Object call() {
					return database.query(ContactsDatabaseHelper.TABLE_CONTACTS,
							ALL_COLUMNS, ContactsDatabaseHelper.COL_ID + " = " + args[0], null,
							null, null, null);
				}
			});
			if(cursor.getCount() == 0) {
				contact = new Contact();
			} else {
				cursor.moveToFirst();
				contact = cursorToContact(cursor);
			}
			
		}
		return contact;
	}
	//Query the Database to retrieve a list of contacts
	public List<Contact> getAllContacts() {
		List<Contact> contacts = new ArrayList<Contact>();
		@SuppressWarnings({ "unchecked", "rawtypes" })
		Cursor cursor = DatabaseThread.call(new DatabaseThread(database, (Object[])ALL_COLUMNS) {
			public Object call() {
				return database.query(ContactsDatabaseHelper.TABLE_CONTACTS,
						(String[])args, null, null, null, null, null);
			}
		});
		cursor.moveToFirst();
		while (!cursor.isAfterLast()) {
			Contact contact = cursorToContact(cursor);
			contacts.add(contact);
			cursor.moveToNext();
		}
		// Make sure to close the cursor
		cursor.close();
		return contacts;
	}

	private Contact cursorToContact(Cursor cursor) {
		
		Contact contact = new Contact();
		contact.setID(cursor.getLong(0));
		contact.setName(cursor.getString(1));
		contact.setAddress(cursor.getString(2));
		contact.setHomePhoneNumber(cursor.getString(3));
		contact.setCellPhoneNumber(cursor.getString(4));
		contact.setAlternatePhoneNumber(cursor.getString(5));
		contact.setEmail(cursor.getString(6));
		contact.setComments(cursor.getString(7));
		
		return contact;
	}
}